﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace HeartLess.Core.Input
{
    class XboxInput : IInput
    {
        private GamePadState _currentGamePadState;
        private GamePadState _previousGamePadState;
        private MouseState _previousMouseState;
        private MouseState _currentMouseState;

        private readonly PlayerIndex _playerIndex;

        private const float STICK_SENSITIVITY = .8f; //500 pixels per second
        private const float STICK_DEAD_ZONE = .1f;

        private bool _allowRepeat;

        public XboxInput(int playerId)
        {
            _playerIndex = (PlayerIndex) playerId - 1;
        }

        void IInput.Initialize()
        {
            _currentGamePadState = GamePad.GetState(_playerIndex);
            _currentMouseState = Mouse.GetState();
        }

        void IInput.Update(GameTime gameTime)
        {
            _previousGamePadState = _currentGamePadState;
            _currentGamePadState = GamePad.GetState(_playerIndex);

            _previousMouseState = _currentMouseState;
            _currentMouseState = Mouse.GetState();

            int deltaX = 0, deltaY = 0;

            float leftStickX = _currentGamePadState.ThumbSticks.Left.X;
            if (Math.Abs(leftStickX) > STICK_DEAD_ZONE)
            {
                deltaX = (int)(gameTime.ElapsedGameTime.Milliseconds * (STICK_SENSITIVITY * leftStickX));
            }

            float leftStickY = -_currentGamePadState.ThumbSticks.Left.Y;
            if (Math.Abs(leftStickY) > STICK_DEAD_ZONE)
            {
                deltaY = (int)(gameTime.ElapsedGameTime.Milliseconds * (STICK_SENSITIVITY * leftStickY));
            }

            int newPointerLocX = _currentMouseState.X + deltaX;
            int newPointerLocY = _currentMouseState.Y + deltaY;
            Mouse.SetPosition(newPointerLocX, newPointerLocY);
        }

        bool IInput.IsMovingUp
        {
            get
            {
                if (_allowRepeat)
                {
                    return _currentGamePadState.DPad.Up == ButtonState.Pressed;
                }
                else
                {
                    return _currentGamePadState.DPad.Up == ButtonState.Pressed &&
                        _previousGamePadState.DPad.Up == ButtonState.Released;
                }
            }
        }

        bool IInput.IsMovingDown
        {
            get
            {
                if (_allowRepeat)
                {
                    return _currentGamePadState.DPad.Down == ButtonState.Pressed;
                }
                else
                {
                    return _currentGamePadState.DPad.Down == ButtonState.Pressed &&
                        _previousGamePadState.DPad.Down == ButtonState.Released;
                }
            }
        }

        bool IInput.IsMovingLeft
        {
            get
            {
                if (_allowRepeat)
                {
                    return _currentGamePadState.DPad.Left == ButtonState.Pressed;
                }
                else
                {
                    return _currentGamePadState.DPad.Left == ButtonState.Pressed &&
                        _previousGamePadState.DPad.Left == ButtonState.Released;
                }
            }
        }

        bool IInput.IsMovingRight
        {
            get
            {
                if (_allowRepeat)
                {
                    return _currentGamePadState.DPad.Right == ButtonState.Pressed;
                }
                else
                {
                    return _currentGamePadState.DPad.Right == ButtonState.Pressed &&
                        _previousGamePadState.DPad.Right == ButtonState.Released;
                }
            }
        }

        bool IInput.IsPressingPause
        {
            get
            {
                bool currentlyPressing = _currentGamePadState.Buttons.Start == ButtonState.Pressed;
                bool previouslyReleased = _previousGamePadState.Buttons.Start == ButtonState.Released;

                return (currentlyPressing && previouslyReleased); 
            }
        }

        bool IInput.IsPressingSelect
        {
            get
            {
                bool currentlyPressing = _currentGamePadState.Buttons.A == ButtonState.Pressed;
                bool previouslyReleased = _previousGamePadState.Buttons.A == ButtonState.Released;

                bool currentlyLeftClicking = (_currentMouseState.LeftButton == ButtonState.Pressed);
                bool previouslyLeftReleased = (_previousMouseState.LeftButton == ButtonState.Released);

                return ((currentlyPressing && previouslyReleased) || (currentlyLeftClicking && previouslyLeftReleased));
            }
        }

        bool IInput.IsPressingBack
        {
            get
            {
                bool currentlyPressing = _currentGamePadState.Buttons.B == ButtonState.Pressed;
                bool previouslyReleased = _previousGamePadState.Buttons.B == ButtonState.Released;

                return (currentlyPressing && previouslyReleased);
            }
        }

        bool IInput.IsPressingJump
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public bool IsPressingFire
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        Point IInput.PointerLocation
        {
            get
            {
                return new Point(_currentMouseState.X, _currentMouseState.Y);
            }
        }

        bool IInput.DirectionalRepeatAllowed
        {
            set
            {
                _allowRepeat = value;
            }
        }
    }
}

